
#include <BScreen>
#include <BCursor>
#include "member_BWidget.h"
#include "member_BCursor.h"
#include "IGlobal.h"

using namespace BWE;

#define member					(*(member_BCursor*)_ptr)
#define member_allocate()		_ptr = new member_BCursor(this)
#define member_release()		delete (member_BCursor*)_ptr

#ifdef linux
#include <unistd.h>
#include <X11/Xlib.h>

BPoint BCursor::GetPos()
{
	Window root = 0;
	Window child = 0;
	int rx = 0;
	int ry = 0;
	int wx = 0;
	int wy = 0;
	uint32_t mask = 0;
    Window window = DefaultRootWindow(app_display);
	if(False == XQueryPointer(app_display, window, &root, &child, &rx, &ry, &wx, &wy, &mask))
	{
		return BPoint(0, 0);
	}
	return BPoint(rx, ry);
}
BPoint BCursor::GetPos(const BWidget* widget)
{
	IWindow* win = 0;
	if(widget)
	{
		const BWidget* rootWidget = widget->root();
		win = widget_member(rootWidget)->window;
	}
	if(win)
	{
		Window root = 0;
		Window child = 0;
		int rx = 0; 
		int ry = 0; 
		int wx = 0; 
		int wy = 0; 
		uint32_t mask = 0;
		XQueryPointer(win->display, win->rootHwnd, &root, &child, &rx, &ry, &wx, &wy, &mask);
		return BPoint(rx, ry);
	}
	return GetPos();
}
BPoint BCursor::GetPos(const BScreen* screen)
{
	BPoint pos = GetPos();
	if(screen)
		pos -= screen->pos();
	return pos;
}

void BCursor::SetPos(int x, int y)
{
	unsigned int w = 0;
	unsigned int h = 0;
	int dx = x;
	int dy = y;
	XWarpPointer(0, 0, 0, x, y, w, h, dx, dy);
}
void BCursor::SetPos(const BPoint& pos)
{
	unsigned int w = 0;
	unsigned int h = 0;
	int dx = pos.x();
	int dy = pos.y();
	XWarpPointer(0, 0, 0, pos.x(), pos.y(), w, h, dx, dy);
}

void BCursor::SetPos(const BScreen* screen, int x, int y)
{
	if(screen)
	{
		x += screen->pos().x();
		y += screen->pos().y();
	}
	SetPos(x, y);
}
void BCursor::SetPos(const BScreen* screen, const BPoint& pos)
{
	if(screen)
	{
		SetPos(screen->pos() + pos);
	}
	else
	{
		SetPos(pos);
	}
}

#endif

#ifdef _WIN32
#include <Windows.h>

BPoint BCursor::GetPos()
{
	POINT point;
	BOOL ret = ::GetCursorPos(&point);
	return BPoint(point.x, point.y);
}
BPoint BCursor::GetPos(const BWidget* widget)
{
	POINT point;
	BOOL ret = ::GetCursorPos(&point);
	BPoint pos(point.x, point.y);
	if (widget)
	{
		BPoint glpos = widget->globalPos();
		pos.x() -= glpos.x();
		pos.y() -= glpos.y();
	}
	return pos;
}
BPoint BCursor::GetPos(const BScreen* screen)
{
	POINT point;
	BOOL ret = ::GetCursorPos(&point);
	BPoint pos(point.x, point.y);
	if(screen)
		pos -= screen->pos();
	return pos;
}

void BCursor::SetPos(const BPoint& pos)
{
	SetPos(pos.x(), pos.y());
}
void BCursor::SetPos(int x, int y)
{
	BOOL ret = ::SetCursorPos(x, y);
}

void BCursor::SetPos(const BScreen* screen, int x, int y)
{
	BPoint pos(x, y);
	if (screen)
	{
		pos += screen->pos();
	}
	BOOL ret = ::SetCursorPos(pos.x(), pos.y());
}
void BCursor::SetPos(const BScreen* screen, const BPoint& point)
{
	BPoint pos = point;
	if (screen)
	{
		pos += screen->pos();
	}
	BOOL ret = ::SetCursorPos(pos.x(), pos.y());
}
#endif

BCursor::BCursor(CursorType type)
{
	member_allocate();
	member.type = type;
}
BCursor::BCursor(BImage* image)
{
	member_allocate();
	member.type = Cursor_None;
	member.images[Cursor_None] = image;
}
BCursor::BCursor(BImage* image, const BPoint& point, const BSize& size)
{
	member_allocate();
	member.type = Cursor_None;
	member.images[Cursor_None] = image;
	member.point = point;
	member.size = size;
}
BCursor::BCursor(BImage* image, int x, int y, int width, int height)
{
	member_allocate();
	member.type = Cursor_None;
	member.images[Cursor_None] = image;
	member.point.set(x, y);
	member.size.set(width, height);
}
BCursor::~BCursor()
{
	member_release();
}

void BCursor::setType(CursorType type)
{
	member.type = type;
}
CursorType BCursor::type() const
{
	return member.type;
}

bool BCursor::setImage(BImage* image, CursorType type)
{
	if (type >= Cursor_None && type < Cursor_Max)
	{
		member.images[type] = image;
		return true;
	}
	return false;
}
BImage* BCursor::image(CursorType type)
{
	return member.images(type);
}
const BImage* BCursor::image(CursorType type) const
{
	return member.images(type);
}

void BCursor::setPoint(const BPoint& point)
{
	member.point = point;
}
void BCursor::setPoint(int x, int y)
{
	member.point.set(x, y);
}
const BPoint& BCursor::point() const
{
	return member.point;
}

void BCursor::setSize(const BSize& size)
{
	member.size = size;
}
void BCursor::setSize(int width, int height)
{
	member.size.set(width, height);
}
const BSize& BCursor::size() const
{
	return member.size;
}

